package copyengine.ui.touch
{

    import copyengine.log.CELog;

    import flash.geom.Rectangle;

    import starling.core.Starling;
    import starling.display.DisplayObject;
    import starling.events.Touch;
    import starling.events.TouchEvent;
    import starling.events.TouchPhase;

    /**
     *代理掉Touch事件,对上层返回各个事件的Callback
     */
    public final class CETouchProxy
    {
        private var mMaxDragDistance:Number;

        private var mTarget:DisplayObject;

        private var mOnClickCallback:Function;
        private var mOnTouchDownCallback:Function;
        private var mOnTouchUpCallback:Function;
        private var mOnTouchMoveCallback:Function;

        private var mOnTouchDisableClickCallback:Function;

        private var mIsEnabled:Boolean;
        private var mIsPhaseDown:Boolean;
        private var mIsStropProgress:Boolean;

        private var mTouchDownPosX:Number;
        private var mTouchDownPosY:Number;

        /**
         * @param _target                                 目标Mc
         * @param _onClickCallback                        Click事件Callback(回调函数可以有1个参数,为Touch,也可以没有参数)
         * @param _onTouchDownCallback                    Down事件(回调函数可以有1个参数,为为Touch,也可以没有参数)
         * @param _onTouchUpCallback                      Up事件(回调函数可以有1个参数,为为Touch,也可以没有参数)
         * @param _onTouchMoveCallback                    Move事件(回调函数可以有1个参数,为为Touch,也可以没有参数)
         * @param _isStopProgress                         Event是否stopPropagation,防止点穿(默认为True)
         * @param _maxDragDistance                        最大的拖拽距离,当超过该距离时候认为该次点击失效
         *
         */
        public function CETouchProxy(_target:DisplayObject,
                                     _onClickCallback:Function = null,
                                     _onTouchDownCallback:Function = null,
                                     _onTouchUpCallback:Function = null,
                                     _onTouchMoveCallback:Function = null,
                                     _onTouchDisableClickCallback:Function = null,
                                     _isStopProgress:Boolean = false,
                                     _maxDragDistance:Number = 50)
        {
            mTarget = _target;
            mMaxDragDistance = _maxDragDistance;
            mIsStropProgress = _isStopProgress;
            mIsEnabled = true;

            mOnClickCallback = _onClickCallback;
            mOnTouchDownCallback = _onTouchDownCallback;
            mOnTouchUpCallback = _onTouchUpCallback;
            mOnTouchMoveCallback = _onTouchMoveCallback;
            mOnTouchDisableClickCallback = _onTouchDisableClickCallback;

            addListener();
        }

        public function dispose():void
        {
            removeListener();
        }

        //============================================//
        //==Public Interface  Function
        //============================================//

        public function get isEnabled():Boolean { return mIsEnabled; }

        public function set isEnabled(value:Boolean):void {mIsEnabled = value;}


        //========================//
        //==Private  Function
        //=========================//

        private function addListener():void { mTarget.addEventListener(TouchEvent.TOUCH, onTouch); }

        private function removeListener():void { mTarget.addEventListener(TouchEvent.TOUCH, onTouch); }

        private function onTouch(event:TouchEvent):void
        {
            if (mTarget.stage == null) {
                //内部函数优化的时候会把移除屏幕外面的对象removeChildFromParent
                //此时调用mTarget.getBounds函数会报错,因为无法找到stage
                //所以这个时间点直接返回不做后续处理
                return;
            }
            else {
                var touch:Touch = event.getTouch(mTarget);
                if (touch != null) {
                    if (touch.phase == TouchPhase.BEGAN && !mIsPhaseDown) {
                        mIsPhaseDown = true;
                        mTouchDownPosX = touch.globalX;
                        mTouchDownPosY = touch.globalY;

                        tryToCallback(mOnTouchDownCallback, touch);
                        if (mIsStropProgress) {
                            event.stopPropagation();
                            event.stopImmediatePropagation();
                        }
                    }
                    else if (touch.phase == TouchPhase.MOVED && mIsPhaseDown) {
                        var rect:Rectangle = mTarget.getBounds(Starling.current.stage);
                        if (touch.globalX < rect.x - mMaxDragDistance ||
                                touch.globalY < rect.y - mMaxDragDistance ||
                                touch.globalX > rect.x + rect.width + mMaxDragDistance ||
                                touch.globalY > rect.y + rect.height + mMaxDragDistance) {
                            mIsPhaseDown = false
                            tryToCallback(mOnTouchUpCallback, touch);
                        }
                        else {
                            tryToCallback(mOnTouchMoveCallback, touch);
                        }
                    }
                    else if (touch.phase == TouchPhase.ENDED && mIsPhaseDown) {
                        mIsPhaseDown = false;
                        if (touch.globalX < mTouchDownPosX - mMaxDragDistance ||
                                touch.globalY < mTouchDownPosY - mMaxDragDistance ||
                                touch.globalX > mTouchDownPosX + mMaxDragDistance ||
                                touch.globalY > mTouchDownPosY + mMaxDragDistance) {
                            tryToCallback(mOnTouchUpCallback, touch);
                        }
                        else {
                            if (mIsEnabled) {
                                tryToCallback(mOnClickCallback, touch);
                            }
                            else {
                                tryToCallback(mOnTouchDisableClickCallback, touch, true);
                            }
                        }
                    }
                }
            }
        }

        /**
         *
         * @param _callbackFun
         * @param _touch
         * @param _isIgnoreEnableProperty            当已经Disable当前TouchProxy以后只有onTouchDisableClick事件还可以响应
         *                                                                    用于支持功能：按钮Disable(变灰色)点击后可以pop一个面板
         */
        private function tryToCallback(_callbackFun:Function,
                                       _touch:Touch,
                                       _isIgnoreEnableProperty:Boolean = false):void
        {
            if ((_isIgnoreEnableProperty || mIsEnabled) && _callbackFun != null) {
                if (_callbackFun.length == 2) {
                    _callbackFun(mTarget, _touch);
                }
                else if (_callbackFun.length == 1) {
                    _callbackFun(mTarget);
                }
                else if (_callbackFun.length == 0) {
                    _callbackFun();
                }
                else {
                    //Callback定义的参数数量不明
                    CELog.err("CETouchProxy unknown callback arg num with : " + _callbackFun.length);
                }
            }
        }


    }
}
